package com.galaxy.commom.base.utils;

import com.galaxy.commom.base.exception.RequestException;
import com.galaxy.commom.base.jwt.JwtToken;
import com.galaxy.commom.base.message.ResponseCode;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.subject.Subject;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * @author caijinbang
 * @date 2018/9/8 21:43
 */
public class IpUtil {

  /**
   * 本地ip地址
   */
  private final static  String  LOCAL_IP_ADDRESS="127.0.0.1";

  /**
   * 本地ipV6地址
   */
  private final static  String  LOCAL_IPV6_ADDRESS="0:0:0:0:0:0:0:1";

  private IpUtil() {
  }

  /**
   * 获取当前网络ip
   * @param request
   * @return
   */
  public static String getIpAddress(HttpServletRequest request){
    String ipAddress = request.getHeader("x-forwarded-for");
    if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
      ipAddress = request.getHeader("Proxy-Client-IP");
    }
    if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
      ipAddress = request.getHeader("WL-Proxy-Client-IP");
    }
    if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
      ipAddress = request.getRemoteAddr();
      if(IpUtil.LOCAL_IP_ADDRESS.equals(ipAddress) || IpUtil.LOCAL_IPV6_ADDRESS.equals(ipAddress)){
        //根据网卡取本机配置的IP
        InetAddress inetAddress=null;
        try {
          inetAddress = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
          e.printStackTrace();
        }
        ipAddress= inetAddress.getHostAddress();
      }
    }
    //对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割，"***.***.***.***".length() = 15
    if(ipAddress!=null && ipAddress.length()>15){
      if(ipAddress.indexOf(",")>0){
        ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));
      }
    }
    return ipAddress;
  }

  /**
   * 获得MAC地址
   * @param ip
   * @return
   */
  public static String getMACAddress(String ip){
    String str = "";
    String macAddress = "";
    try {
      Process p = Runtime.getRuntime().exec("nbtstat -A " + ip);
      InputStreamReader ir = new InputStreamReader(p.getInputStream());
      LineNumberReader input = new LineNumberReader(ir);
      for (int i = 1; i < 100; i++) {
        str = input.readLine();
        if (str != null) {
          if (str.indexOf("MAC Address") > 1) {
            macAddress = str.substring(str.indexOf("MAC Address") + 14, str.length());
            break;
          }
        }
      }
    } catch (IOException e) {
      e.printStackTrace(System.out);
    }
    return macAddress;
  }

  /**
   * 执行登录
   * @param request
   * @return
   */
  public static boolean executeLogin(ServletRequest request){
    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    String authorization = httpServletRequest.getHeader("Authorization");
    if(authorization==null || "".equals(authorization.trim())){
      throw RequestException.fail("未含授权标示，禁止访问");
    }
    JwtToken token = new JwtToken(authorization,null,null);
    // 提交给realm进行登入，如果错误他会抛出异常并被捕获
    Subject subject = SecurityUtils.getSubject();
    try {
      subject.login(token);
    }catch (DisabledAccountException e){
      if(e.getMessage().equals("verifyFail")){
        throw new RequestException(ResponseCode.NOT_SING_IN.code,"身份已过期，请重新登录",e);
      }
      throw new RequestException(ResponseCode.SIGN_IN_INPUT_FAIL.code,e.getMessage(),e);
    }catch (Exception e){
      e.printStackTrace();
      throw new RequestException(ResponseCode.SIGN_IN_FAIL,e);
    }
    // 如果没有抛出异常则代表登入成功，返回true
    return true;
  }

  public static synchronized void executeLogin(){
    HttpServletRequest request =
        ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    boolean b = IpUtil.executeLogin(request);
    if(!b){
      throw RequestException.fail("身份已过期或无效，请重新认证");
    }
  }

  /**
   * 判断请求是否是Ajax
   * @param request
   * @return
   */
  public static boolean ajax(HttpServletRequest request){
    String accept = request.getHeader("accept");
    return accept != null && accept.contains("application/json") || (request.getHeader("X-Requested-With") != null && request.getHeader("X-Requested-With").contains("XMLHttpRequest"));
  }
}
